package cn.fastpay.user.security;

import cn.fastpay.core.exception.BaseException;
import cn.fastpay.core.security.UserSecurityConstant;
import cn.fastpay.core.vo.LoginUser;
import cn.fastpay.user.exception.UserException;
import cn.fastpay.user.utils.RSAUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.interfaces.RSAPrivateKey;
import java.util.Date;


/**
 * @author freewolf
 */
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;

    public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException {
        try {
            LoginUser user = new ObjectMapper().readValue(req.getInputStream(), LoginUser.class);
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
            return authenticationManager.authenticate(token);
        } catch (BadCredentialsException e) {
            throw UserException.USER_PASSWORD_WRONG;
        } catch (LockedException e) {
            throw UserException.USER_LOCKED;
        } catch (UsernameNotFoundException e){
            throw UserException.USER_NOT_FOUND;
        } catch (Exception e) {
            throw BaseException.UNKNOWN_ERROR;
        }
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
                                            Authentication auth) throws IOException {
        // 从Application中取出私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) req.getServletContext().getAttribute("privateKey");
        if (privateKey == null) {
            privateKey = RSAUtil.getPrivateKey();
            req.getServletContext().setAttribute("privateKey", privateKey);
        }

        User user = (User) auth.getPrincipal();
        String token = Jwts.builder()
                .setSubject(user.getUsername())
                .setExpiration(new Date(System.currentTimeMillis() + UserSecurityConstant.EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.RS256, privateKey)
                .compact();
        res.getWriter().println("{\"code\": 0, \"message\": \"success\", \"data\": \""+ token +"\"}");
//        responseContent(0, "success", token, res);
    }

//    private Authentication responseContent(Integer code, String msg, Object data, HttpServletResponse res) {
//        try {
//            res.setContentType("application/json; charset=utf-8");
//            res.getWriter().write("{\"code\": "+ code +", \"message\": \"" + msg + "\", \"data\": \""+ data +"\"}");
//        } catch (IOException e) {
//            e.printStackTrace();
//        } finally {
//            try {
//                res.getWriter().close();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
//        return null;
//    }
}

